import asyncio
import logging

logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(message)s")


class TaskManager:
    """任务管理器"""

    def __init__(self):
        self.tasks = set()

    async def worker(self, name, duration):
        """工作协程"""
        logging.info(f"任务 {name} 开始")
        try:
            await asyncio.sleep(duration)
            logging.info(f"任务 {name} 完成")
            return f"{name}_result"
        except asyncio.CancelledError:
            logging.info(f"任务 {name} 被取消")
            raise

    async def create_tasks(self, count):
        """创建多个任务"""
        for i in range(count):
            task = asyncio.create_task(
                self.worker(f"worker_{i}", i + 1), name=f"task_{i}"
            )
            self.tasks.add(task)

            """
            Task.add_done_callback(fn) 用来在 Task 完成（完成、抛异常或被取消）时注册一个回调，
            回调会接收该 Task/Future 作为唯一参数并在事件循环线程中被调用。

            要点

            回调签名：fn(future: asyncio.Future) -> None。
            回调在 Task 状态变为 done 时被执行（如果在已完成的 Task 上添加，回调会立即被调度/调用）。
            回调不能被 await（如果需要运行协程，回调里应用 asyncio.create_task 去调度它）。
            常用场景：清理（如从集合中移除 task）、记录结果/异常、触发后续同步逻辑。
            在回调中读取结果要用 future.result()（可能抛异常）或 future.exception() 来安全处理异常/取消。
            """
            task.add_done_callback(self.tasks.discard)

        logging.info(f"创建了 {count} 个任务")

    async def monitor_tasks(self):
        """监控任务状态"""
        while True:
            running_tasks = [t for t in self.tasks if not t.done()]
            logging.info(f"运行中的任务: {len(running_tasks)}")

            if not running_tasks:
                break

            await asyncio.sleep(0.5)

    async def cancel_all_tasks(self):
        """取消所有任务"""
        logging.info("取消所有任务")
        for task in self.tasks:
            task.cancel()

        await asyncio.gather(*self.tasks, return_exceptions=True)


async def task_management():
    """任务管理演示"""
    manager = TaskManager()

    await manager.create_tasks(5)
    monitor_task = asyncio.create_task(manager.monitor_tasks())

    await asyncio.sleep(2)
    await manager.cancel_all_tasks()

    await monitor_task


asyncio.run(task_management())
